package com.youku.mson.type;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.youku.mson.util.ReflectUtils;
import com.youku.mson.util.TypeAdapter;
import com.youku.mson.util.TypeUtils;

public class ObjectJsonValue implements JsonValue {

	private List<JsonValue> members;

	public ObjectJsonValue(List<JsonValue> members) {
		this.members = members;
	}

	@Override
	public Object read(TypeAdapter adapter) {
		Class<?> targetClass = adapter.getTargetClass();
		if (TypeUtils.isMap(targetClass)) {
			return createMap(adapter);
		} else {
			return createObject(adapter);
		}
	}

	private Object createMap(TypeAdapter adapter) {
		Map<String, Object> map = new HashMap<>();
		for (JsonValue member : members) {
			PairJsonValue pair = (PairJsonValue) member;
			String fieldName = pair.getKey();
			JsonValue fieldValue = pair.getValue();

			Class<?> valueClass = null;
			Type type = adapter.getType();
			if (type instanceof ParameterizedType) {
				ParameterizedType pt = (ParameterizedType) type;
				valueClass = (Class<?>) pt.getActualTypeArguments()[1];
			} else {
				valueClass = Object.class;
			}

			map.put(fieldName, fieldValue.read(new TypeAdapter(valueClass)));
		}
		return map;
	}

	private Object createObject(TypeAdapter adapter) {
		Class<?> targetClass = adapter.getTargetClass();
		Object obj = ReflectUtils.newInstance(targetClass);

		for (JsonValue member : members) {
			PairJsonValue pair = (PairJsonValue) member;
			String fieldName = pair.getKey();
			JsonValue fieldValue = pair.getValue();

			Field field = ReflectUtils.getDeclaredField(targetClass, fieldName);

			Class<?> elementClass = field.getType();

			Type type = field.getGenericType();

			TypeAdapter adt = new TypeAdapter(elementClass, type);
			ReflectUtils.invokeSetter(obj, fieldName, new Class<?>[] { elementClass },
					new Object[] { fieldValue.read(adt) });

		}
		return obj;
	}
}
